# 类 ：描述一种事物，包括特征和行为，就像图纸一样
"""
# 在代码中类包含属性和函数来表示特征行为

class Washer():
    # 魔法方法init，用来初始化对象
    # 在对象创建时会自动调用
    def __init__(self, height):
        self.weight = 500
        self.height = height
    # 魔法方法str，当输出对象时，返回相应内容，如类的状态或说明
    def __str__(self):
        return '洗衣机介绍'

    def water(self):
        print("开始洗")
        print(self)
        # self参数不需要手动传入，解释器会自动将当前引用的对象传递过去

    def w_info(self):
        # 在类的内部调用对象的属性
        print(f'{self.weight}')
        print(f'{self.height}')


haier = Washer(300)     # 此处的参数时init初始化的参数
haier.water()
# print(haier)
# self与haier的内存地址相同，说明self就表示调用函数的对象

# 在类外面设置属性，该属性只属于这个对象的私有属性,取值时外面的优先
# haier.weight = 100
# haier.height = 200
# print(haier.weight)
haier.w_info()
"""

# 烤地瓜案例
"""
class sweet_potato():
    def __init__(self):
        # 时间
        self.cook_time = 0
        # 状态
        self.cook_status = "生的"
        # 调料
        self.condiment = []

    def __str__(self):
        return f"这个地瓜烤了{self.cook_time}分钟,状态为{self.cook_status}" \
               f"调料为：{self.condiment}"

    def cook(self, time):
        self.cook_time += time
        if self.cook_time < 3:
            self.cook_status = "生的"
        elif self.cook_time <= 5:
            self.cook_status = "半生不熟"
        elif self.cook_time < 8:
            self.cook_status = "熟了"
        elif self.cook_time >= 8:
            self.cook_status = "糊了"

    def add_condiment(self, c):
        self.condiment.append(c)


p1 = sweet_potato()
p1.cook(3)
p1.add_condiment('盐')
print(p1.cook_status)
p1.cook(3)
p1.add_condiment('胡椒')
print(p1.cook_status)
print(p1)
"""

# 搬家具
""" class Furniture():
    def __init__(self, name, area):
        self.name = name
        self.area = area

class Home():
    def __init__(self, area, address):
        self.address = address
        self.area = area
        self.free_ares = area
        self.furniture_list = []

    def __str__(self):
        return f'当前位置为{self.address},面积为{self.area},剩余面积为{self.free_ares},' \
               f'当前已有家具{self.furniture_list}'

    def add_furniture(self, f):
        if self.area >= f.area:
            self.furniture_list.append(f.name)
            self.free_ares -= f.area
            print(f"{f.name}搬入成功")
        else:
            print("面积不足")


f1 = Furniture('沙发',20)
h1 = Home(150, "biejing")
print(h1.add_furniture(f1))
print(h1)
"""

# 单继承
# object为基类，所有派生类都默认继承与基类
"""
class father(object):
    def __init__(self):
        self.name = "bai"

    def __str__(self):
        return "father"

    def p(self):
        print(self.name)


class child(father):
    pass


c1 = child()
print(c1)
print(c1.name)
c1.p()

"""

# 多继承
"""

class father1(object):
    def __init__(self):
        self.name = "bai"

    def __str__(self):
        return "father"

    def p(self):
        print(self.name)


class father2(object):
    def __init__(self):
        self.name = "bai2"

    def __str__(self):
        return "father2"

    def p(self):
        print(self.name)


class child(father1, father2):
    pass


# 在多继承中，若有同样的属性与方法名，优先调用第一个父类
c1 = child()
print(c1)
print(c1.name)
c1.p()
print(child.__mro__)
"""

# 子类重写父类方法，并调用父类方法,和私有方法及属性
class father(object):
    def __init__(self):
        self.name = "bai"
        self.__money = 20000   # 私有属性和方法不会继承给子类只能在类内部调用,
        # 私有属性用set_xx修改，用get_xx取值

    def __str__(self):
        return "father"

    def p(self):
        print(self.name)

    def get_money(self):
        return self.__money
    def get_p_money(self):
        return self.__p_money()

    def __p_money(self):        # 私有方法
        print(self.__money)


class child(father):
    def __init__(self):
        self.name = "wang"

    def __str__(self):
        return "child"

    def p(self):
        # 若之前调用过父类并初始化，父类会将子类的属性覆盖，所以要重新初始化子类
        self.__init__()
        print(self.name)

    def do_father(self):
        # 在调用父类方法时又重新初始化
        # father.__init__(self)
        # father.p(self)
        # super用法(调用父类的方法和属性)
        super().__init__()
        super().p()

# 在子类中重写父类方法时，只会调用子类的方法或属性
c1 = child()
f1 = father()
print(c1)
print(c1.name)
c1.p()
c1.do_father()
# c1.__money()
print(f1.get_money())
f1.get_p_money()
print(child.__mro__)

